home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
EnigmA Amiga Run 1996 March
/
EnigmA AMIGA RUN 05 (1996)(G.R. Edizioni)(IT)[!][issue 1996-03][Skylink CD IV].iso
/
earcd
/
editor
/
chktex.lha
/
chktex
/
source
/
Utility.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-01-25
|
10KB
|
577 lines
/*
* ChkTeX v1.2, utility functions.
* Copyright (C) 1995-96 Jens T. Berger Thielemann
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* Contact the author at:
* Jens Berger
* Spektrumvn. 4
* N-0666 Oslo
* Norway
* E-mail: <jensthi@ifi.uio.no>
*
*
*/
#include "ChkTeX.h"
/***************************** SUPPORT FUNCTIONS ************************/
/*
* Copies a string with a maximum length of `len' starting at `pos' in
* `source' into `dest'.
* Returns -1 if the pos value is beyond the length of the source value,
* else NULL.
*/
#ifdef STRMID_NEED
WORD strmid(const STRPTR source, STRPTR dest, LONG pos, LONG len)
{
ULONG slen = strlen(source);
STRPTR Start;
WORD Retval = -1;
if(len)
{
if(slen > pos)
{
Start = &source[pos];
while((len-- > 0) && (*dest++ = *Start++))
;
*dest++ = 0;
if(len == -1)
Retval = 0;
}
}
else
{
*dest = 0;
Retval = 0L;
}
return(Retval);
}
#endif
/*
* Determine whether a file exists.
*
*/
BOOL fexists(STRPTR Filename)
{
BOOL Retval = FALSE;
#if defined(F_OK) && defined(R_OK)
Retval = access(Filename, F_OK|R_OK) == 0;
#else
{
FILE *fh;
if(fh = fopen(Filename, "r"))
{
Retval = TRUE;
fclose(fh);
}
}
#endif
return(Retval);
}
/*
* 'Safe' memset() replacement.
* Just tries to check the parameters, so that the risk of killing
* innocent memory is lowered.
* Please note that the `n' parameter now is an signed longword, not
* an size_t. Won't permit that `n' exceeds BUFLEN, nor negative sizes.
* Returns `to' if some memset()'ing was done, NULL if not.
*/
APTR sfmemset(APTR to, int c, LONG n)
{
if(to && (n > 0))
{
n = min(n, BUFLEN);
return(memset(to, c, (size_t) n));
}
return(NULL);
}
/*
* Concatenates the `File' string to the `Dir' string, leaving the result
* in the `Dir' buffer. Takes care of inserting `directory' characters;
* if we've got the strings "/usr/foo" and "bar", we'll get
* "/usr/foo/bar".
*
* Behaviour somewhat controlled by the macros SLASH and DIRCHARS in the
* .h file.
*
*/
void tackon(STRPTR Dir, const STRPTR File)
{
UBYTE EndC;
ULONG SLen;
if(Dir && (SLen = strlen(Dir)))
{
EndC = Dir[SLen -1];
ifn(strchr(DIRCHARS, EndC))
{
Dir[SLen++] = SLASH;
Dir[SLen ] = 0L;
}
}
strcat(Dir, File);
}
/*
* Quick replace function
* Replaces every occurrence of a character in a string with another one.
*/
void strrep( STRPTR String, /* String to replace within. */
const UBYTE From, /* Character to search for. */
const UBYTE To) /* Character to put instead. */
{
while(String = strchr(String, From))
*String++ = To;
}
/*
* Strips tail and/or front of a string
* Kills trailing/leading spaces. The macro/function SKIP_STRIP(char c)
* is used to decide whether a space should be skipped. This function
* should return TRUE if the character should be skipped, FALSE if not.
* Returns the string which was passed onto it.
*/
STRPTR strip( STRPTR str, /* String to strip */
const WORDBITS flags) /* One of the following: */
/* STRP_LFT - Strips leading blanks */
/* STRP_RGT - Strips trailing blanks */
/* STRP_BTH - Strips on both sides */
{
STRPTR bufptr = str, nlptr;
UBYTE c;
if(bufptr && (c = *bufptr))
{
if(flags & STRP_LFT)
{
if(SKIP_STRIP(c) && c)
{
do
{
c = *++bufptr;
} while(SKIP_STRIP(c) && c);
}
}
if(flags & STRP_RGT)
{
if(c && *bufptr)
{
nlptr = bufptr;
while(*++nlptr);
do
{
nlptr[0] = 0;
c = *--nlptr;
} while(SKIP_STRIP(c) && c && (nlptr > bufptr));
}
else
*bufptr = 0;
}
}
return(bufptr);
}
/*
* Make a sign of life.
* Displays a rotating line, displayed using the characters \|/-. Each
* call will progress the line one position. Useful for notifying the user
* that something in fact is happening.
*
*/
void tictoc(void)
{
#ifndef NO_TICTOC
static const
UBYTE Frames [] = "\\|/-";
static
UWORD Offset = 0L;
putc(Frames[Offset++], stderr);
putc('\r', stderr);
fflush(stderr);
Offset &= 3;
#else
return;
#endif
}
/*
* Converts all the chars in the string passed into uppercase.
*/
#ifdef STRUPR_NEED
STRPTR strupr(STRPTR String)
{
STRPTR Bufptr;
UBYTE TmpC;
for(Bufptr = String;
TmpC = *Bufptr;
Bufptr++)
*Bufptr = toupper(TmpC);
return(String);
}
#endif
/*
* Returns a duplicate of the string passed.
*/
#ifdef STRDUP_NEED
STRPTR strdup(const STRPTR String)
{
STRPTR Retval = NULL;
size_t Len;
if(String)
{
Len = strlen(String) + 1;
if(Retval = malloc(strlen(String) + 1))
{
memcpy(Retval, String, Len);
}
}
return(Retval);
}
#endif
/*
* Allocates a with the length n, and copies the contents of `b' into
* that one.
*/
void *realloc_ (void *b, size_t n)
{
void *Retval = NULL;
if(n)
{
if((Retval = calloc(n, sizeof(UBYTE))) && b)
{
memcpy(Retval, b, n);
free(b);
}
}
else
free(b);
return(Retval);
}
/*************************** WORDLIST HANDLING **************************/
/*
* Inserts a duplicate of `Word' into the `Wordlist' structure. You do thus
* not need to make a duplicate of `Word' yourself.
*/
BOOL InsertWord(const STRPTR Word, struct WordList *WL)
{
STRPTR WrdCpy;
if(WrdCpy = strdup(Word))
{
if(StkPush(WrdCpy, &WL->Stack))
{
WL->Sorted = FALSE;
return(TRUE);
}
free(WrdCpy);
}
return(FALSE);
}
/*
* Query whether a `Word' is previously InsertWord()'ed into the WL
* structure. Does case-sensitive comparison.
*/
BOOL HasWord(const STRPTR Word, struct WordList *WL)
{
if(WL && WL->Stack.Used && Word)
{
ifn(WL->Sorted)
{
qsort(&WL->Stack.Data[0], (size_t) WL->Stack.Used, sizeof(APTR), &str_cmp);
WL->Sorted = TRUE;
}
if(bsearch(&Word, &WL->Stack.Data[0], (size_t) WL->Stack.Used, sizeof(APTR), &str_cmp))
return(TRUE);
}
return(FALSE);
}
int str_cmp(const void *a, const void *b)
{
return(strcmp(*((STRPTR *) a), *((STRPTR *) b)));
}
/************************** GENERIC STACK ******************************/
/*
* Push something onto a stack. Returns TRUE if successful, else FALSE.
* Note: You can not push a NULL Data element.
*/
BOOL StkPush(const APTR Data, struct Stack *Stack)
{
ULONG NewSize;
APTR *NewBuf;
if(Data && Stack)
{
if(Stack->Used >= Stack->Size)
{
NewSize = Stack->Size?
(Stack->Size * 3)/2 :
MINPUDDLE * sizeof(APTR);
if(NewBuf = realloc(Stack->Data, (size_t) NewSize))
{
Stack->Size = NewSize;
Stack->Data = NewBuf;
}
else
return(FALSE);
}
Stack->Data[Stack->Used++] = Data;
return(TRUE);
}
return(FALSE);
}
/*
* Pops an element from the stack.
*
*/
APTR StkPop(struct Stack *Stack)
{
APTR Retval = NULL;
if(Stack && (Stack->Used > 0))
{
Retval = Stack->Data[--Stack->Used];
#ifdef NO_DIRTY_TRICKS
{
APTR *NewBuf;
if(Stack->Used < (Stack->Size/2))
{
ULONG NewSize;
NewSize = (Stack->Size * 2)/3;
NewSize = max(NewSize, MINPUDDLE * sizeof(APTR));
if(NewBuf = realloc(Stack->Data, (size_t) NewSize))
{
Stack->Size = NewSize;
Stack->Data = NewBuf;
}
}
}
#endif
}
return(Retval);
}
/*
* Returns the topmost element of the stack.
*/
APTR StkTop(struct Stack *Stack)
{
APTR Retval = NULL;
if(Stack && (Stack->Used > 0))
Retval = Stack->Data[Stack->Used - 1];
return(Retval);
}
/************************** CHARACTER STACK ******************************/
/*
* Pushes the character on the stack.
*/
BOOL PushChar(const UBYTE c, const ULONG Line,
const ULONG Column, struct Stack *Stk,
const STRPTR LineCpy)
{
struct CharInfo *ci;
if(ci = malloc(sizeof(struct CharInfo)))
{
ci->Char = c;
ci->Line = Line;
ci->Column = Column;
ci->LineBuf = LineCpy;
if(StkPush(ci, Stk))
{
return(TRUE);
}
free(ci);
}
return(FALSE);
}
/*
* Returns and removes a character from the stack, returns NULL if
* the stack is empty.
*/
struct CharInfo *PopChar(struct Stack *Stack)
{
return((struct CharInfo *) StkPop(Stack));
}
/*
* Same as PopChar(), but lets the character alone on the stack.
*/
struct CharInfo *TopChar(struct Stack *Stack)
{
return((struct CharInfo *) StkTop(Stack));
}
/************************* OPEN/CLOSE COUNTING **************************/
/*
* Returns the index a given bracket (`()[]{}') character has in the
* BrOrder array. Returns ~0 if the character was not a bracket.
*/
ULONG BrackIndex(const UBYTE c)
{
ptrdiff_t Retval;
/*
* We should really use a strchr() into the BrOrder array,
* but this is hopefully faster...this routine is one of the
* most called functions in the whole program.
*/
#ifndef NO_DIRTY_TRICKS
switch(c)
{
case '(': Retval = 0; break;
case ')': Retval = 1; break;
case '[': Retval = 2; break;
case ']': Retval = 3; break;
case '{': Retval = 4; break;
case '}': Retval = 5; break;
default: Retval = ~0UL; break;
}
#else
{
STRPTR Ptr;
Retval = ~0UL;
if(c && (Ptr = strchr(BrOrder, c)))
Retval = Ptr - BrOrder;
}
#endif
return((ULONG) Retval);
}
/*
* Counts brackets for you. Give it a bracket, and it will update the
* corresponding counter.
*/
void AddBracket(const UBYTE c)
{
LONG Index;
if((Index = BrackIndex(c)) != ~0UL)
{
Brackets[Index]++;
}
}
/*
* Returns the character that matches the given bracket, NULL if `c'
* wasn't a bracket character.
*/
UBYTE MatchBracket(const UBYTE c)
{
ULONG Index;
UBYTE Char = 0;
if((Index = BrackIndex(c)) != ~0UL)
Char = BrOrder[Index ^ 1];
return(Char);
}